using Circus.CodeEditor;

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using System.Text.RegularExpressions;
namespace Circus.Syntax.Lexer
{
	public class LexState 
	{
		private string name = string.Empty;
		private string desc = string.Empty;
		private bool caseSensitive;
		private LexSyntaxBlocks syntaxBlocks;
		private string expression = string.Empty;
		private Regex regex;
		private Dictionary<int, LexSyntaxBlock> blocks;
		private LexScheme scheme;
		[Description("Gets or sets \"ILexScheme\" that owns this \"LexState\".")]
		public virtual LexScheme Scheme
		{
			get
			{
				return this.scheme;
			}
			set
			{
				if (this.scheme != value)
				{
					this.scheme = value;
					this.OnSchemeChanged();
				}
			}
		}
		[Description("Gets or sets name of the \"LexState\".")]
		public virtual string Name
		{
			get
			{
				return this.name;
			}
			set
			{
				if (this.name != value)
				{
					this.name = value;
					this.OnNameChanged();
				}
			}
		}
		[Description("Gets or sets description of the \"ILexState\".")]
		public virtual string Desc
		{
			get
			{
				return this.desc;
			}
			set
			{
				if (this.desc != value)
				{
					this.desc = value;
					this.OnDescChanged();
				}
			}
		}
		[Description("Gets or sets a value indicating whether the analizer should perform case sensitive parsing for this \"LexState\".")]
		public virtual bool CaseSensitive
		{
			get
			{
				return this.caseSensitive;
			}
			set
			{
				if (this.caseSensitive != value)
				{
					this.caseSensitive = value;
					this.OnCaseSensitiveChanged();
				}
			}
		}
		[Description("Represents a collective regular expression pattern for the \"LexState\".")]
		public virtual string Expression
		{
			get
			{
				return this.expression;
			}
		}
		[Description("Gets or sets a collection of lexical syntax blocks.")]
		public virtual LexSyntaxBlocks SyntaxBlocks
		{
			get
			{
				return this.syntaxBlocks;
			}
			set
			{
				this.syntaxBlocks.Clear();
				using (IEnumerator<LexSyntaxBlock> enumerator = value.GetEnumerator())
				{
					while (enumerator.MoveNext())
					{
						LexSyntaxBlock item = (LexSyntaxBlock)enumerator.Current;
						this.syntaxBlocks.Add(item);
					}
				}
				this.OnBlocksChanged();
			}
		}
		[Description("Represents a regular expression that contains \"Expression\" as a pattern.")]
		public virtual Regex Regex
		{
			get
			{
				return this.regex;
			}
		}
		[Description("Represents index of the \"LexState\" within the lexical state collection.")]
		public virtual int Index
		{
			get
			{
				return (this.scheme != null) ? this.scheme.States.IndexOf(this) : -1;
			}
		}
		public virtual Dictionary<int, LexSyntaxBlock> Blocks
		{
			get
			{
				return this.blocks;
			}
		}
		
		private void InitBlockHash()
		{
			this.blocks.Clear();
			int[] groupNumbers = this.regex.GetGroupNumbers();
			int[] array = groupNumbers;
			for (int i = 0; i < array.Length; i++)
			{
				int num = array[i];
				string text = this.regex.GroupNameFromNumber(num);
				if (text != null && text.Length > 0 && text[0] == '_')
				{
					int index = int.Parse(text.Substring(1));
					this.blocks.Add(num, this.syntaxBlocks[index]);
				}
			}
		}
		private void BuildExpression(bool update)
		{
			StringBuilder stringBuilder = new StringBuilder();
			using (IEnumerator<LexSyntaxBlock> enumerator = this.syntaxBlocks.GetEnumerator())
			{
				while (enumerator.MoveNext())
				{
					LexSyntaxBlock lexSyntaxBlock = (LexSyntaxBlock)enumerator.Current;
					lexSyntaxBlock.CaseSensitive = this.caseSensitive;
					string text = lexSyntaxBlock.Expression;
					if (text != null && text != string.Empty)
					{
						stringBuilder.Append(string.Format("(?<{0}>{1})", "_" + lexSyntaxBlock.Index.ToString(), text) + "|");
					}
				}
			}
			if (stringBuilder.Length > 0)
			{
				stringBuilder.Remove(stringBuilder.Length - 1, 1);
			}
			this.UpdateExpression(stringBuilder.ToString(), update);
		}
		protected void UpdateExpression(string expr, bool update)
		{
			if (this.expression != expr || update)
			{
				this.expression = expr;
				RegexOptions regexOptions = RegexOptions.ExplicitCapture | RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.IgnorePatternWhitespace;
				if (!this.caseSensitive)
				{
					regexOptions |= RegexOptions.IgnoreCase;
				}
				this.regex = new Regex(expr, regexOptions);
				this.InitBlockHash();
			}
		}
		protected virtual void OnCaseSensitiveChanged()
		{
			this.BuildExpression(true);
		}
		protected virtual void OnBlocksChanged()
		{
			this.BuildExpression(false);
		}
		protected virtual void OnSchemeChanged()
		{
		}
		protected virtual void OnNameChanged()
		{
		}
		protected virtual void OnDescChanged()
		{
		}
		public LexState()
		{
			this.syntaxBlocks = new LexSyntaxBlocks(this);
			this.regex = new Regex(string.Empty);
			this.blocks = new Dictionary<int, LexSyntaxBlock>();
		}
		public LexState(LexScheme scheme) : this()
		{
			this.scheme = scheme;
		}
		public virtual void ResetCaseSensitive()
		{
			this.CaseSensitive = false;
		}
	}
}
